package com.perfma.xtest.cmd;

import jodd.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ExecutorBizImpl implements ExecutorBiz {

    private static Logger logger = LoggerFactory.getLogger(ExecutorBizImpl.class);

    private static ExecutorBiz instance = new ExecutorBizImpl();

    public static ExecutorBiz getInstance() {
        return instance;
    }

    private static Map<Long, String> scriptPool = new ConcurrentHashMap<>();

    public static Map<Long, String> getScriptPool() {
        return scriptPool;
    }


    @Override
    public ReturnT<String> kill(long jobId, String because) {
        // kill handlerThread, and create new one
        JobThread jobThread = JobExecutor.loadJobThread(jobId);
        if (jobThread != null) {
            JobExecutor.removeJobThread(jobId, because);
            logger.info("任务-{},任务终止开始操作", jobId);
            String uniqueName = scriptPool.get(jobId);
            if (!StringUtil.isBlank(uniqueName)) {
                logger.info("任务-{},任务已指定标识符,通过shell终止开始", jobId);
                ExecutorBiz executorBiz = new ExecutorBizImpl();
                TriggerParam triggerParam = new TriggerParam();
                triggerParam.setJobId(Long.MAX_VALUE - jobId);
                logger.info("任务转换原始jobId:{},生成新的jobId:{},防止队列中有任务冲突.", jobId, Long.MAX_VALUE - jobId);
                triggerParam.setJobType(JobType.KILLJOB);
                String command = "ps -ef|grep ".concat(uniqueName).concat("|grep -v grep|awk '{print $2}'| xargs kill -9");
                triggerParam.setGlueSource(command);
                triggerParam.setUniqueName(jobId + "-kill");
                triggerParam.setCallBackBiz(new KillProcessCallBackHandle());
                executorBiz.run(triggerParam);
                logger.info("任务-{},任务已指定标识符,通过shell终止结束", jobId);
            }
            return ReturnT.SUCCESS;
        }

        return new ReturnT<String>(ReturnT.SUCCESS_CODE, "任务已被终止");
    }

    @Override
    public ReturnT<LogResult> log(long logDateTim, long logId, Integer fileSize) {
        String logFileName = JobFileAppender.makeLogFileName(logId);
        LogResult logResult = JobFileAppender.readLog(logFileName, fileSize);
        return new ReturnT<>(logResult);
    }

    @Override
    public ReturnT<String> run(TriggerParam triggerParam) {
        logger.info("[执行器] 收到任务ID为:{} ", triggerParam.getJobId());
        ReturnT<String> pushResult = null;
        if (triggerParam.getJobType() != null && triggerParam.getJobType().equals(JobType.KILLJOB)) {
            logger.info("任务ID为:{} 该任务为终止任务,可以直接进行", triggerParam.getJobId());
            JobThread jobThread = JobExecutor.registJobThread(triggerParam.getJobId());
            pushResult = jobThread.pushTriggerQueue(triggerParam);
            return pushResult;
        } else {
            if (scriptPool.get(triggerParam.getJobId()) != null) {
                logger.error("任务重复执行, 任务ID为:{}", triggerParam.getJobId());
                return new ReturnT<String>(ReturnT.FAIL_CODE, "任务重复执行, 任务ID为:" + triggerParam.getJobId());
            }
            scriptPool.put(triggerParam.getJobId(), triggerParam.getUniqueName());
            logger.info("往scriptPool里面添加任务，jobId={}", triggerParam.getJobId());
            int jobSize = JobExecutor.getJobThreadRepository().size();
            if (jobSize > 5) {
                boolean canExec = false;
                Collection<JobThread> collection = JobExecutor.getJobThreadRepository().values();
                for (JobThread jobThread : collection) {
                    if (jobThread != null && !jobThread.isRunningOrHasQueue()) {
                        pushResult = jobThread.pushTriggerQueue(triggerParam);
                        return pushResult;
                    }
                }
                if (!canExec) {
                    return new ReturnT<String>(ReturnT.FAIL_CODE, "任务已满，请稍后再试.");
                }
            } else {
                logger.info("当前共有任务{},启动新线程执行任务: {}", jobSize, triggerParam.getJobId());
                JobThread jobThread = JobExecutor.registJobThread(triggerParam.getJobId());
                pushResult = jobThread.pushTriggerQueue(triggerParam);
            }
            return pushResult;
        }
    }
}

class KillProcessCallBackHandle implements CallBackBiz {
    private static Logger logger = LoggerFactory.getLogger(KillProcessCallBackHandle.class);

    @Override
    public ReturnT<String> callback(HandleCallbackParam callbackParam) {
        logger.info("任务-{},手动终止gatling完毕,结果为:{}", callbackParam.getLogId(),
                callbackParam.getExecuteResult().getCode());
        //移除自身线程
        JobExecutor.removeJobThread(callbackParam.getLogId(), "callback触发终止");
        return ReturnT.SUCCESS;
    }
}